#include <Arduino.h>
#include "painlessMesh.h"
#include "DHT.h"

#define DHTPIN 4  
#define DHTTYPE DHT11   

// ESP-MESH 组网鉴权信息，只有信息相同的 ESP32 才可以进行 ESP-MESH 组网
#define MESH_PREFIX "LittleCoke"
#define MESH_PASSWORD "123456hello"
#define MESH_PORT 5555

#define ESP32_NODE 3316138365
#define ESP32C3_NODE 2030530093
#define ESP32S3_NODE 412166304

painlessMesh mesh;
DHT dht(DHTPIN, DHTTYPE);  

Scheduler userScheduler;

// 任务函数声明
void sendMessage();
void readDHT();

// 任务：定期发送数据
Task taskSendMessage(TASK_SECOND * 3, TASK_FOREVER, &sendMessage);
// 任务：定期读取温湿度数据
Task taskReadDHT(TASK_SECOND * 2, TASK_FOREVER, &readDHT);

float temperature = 0.0;
float humidity = 0.0;
float smoke = 0.0;

// 读取DHT数据的任务
void readDHT() {
  temperature = dht.readTemperature();
  humidity = dht.readHumidity();
  Serial.printf("温度：%.2f℃\n", temperature);
  Serial.printf("湿度：%.2f%%RH\n", humidity);
}

// 发送数据任务，ESP32 向 ESP32S3 发送温湿度、烟雾浓度数据，向 ESP32C3 发送数据收到消息
void sendMessage() {
  String msgS3 = "ESP32 Node ";
  msgS3 += mesh.getNodeId();
  msgS3 += " | Temp: " + String(temperature, 2) + "C";
  msgS3 += " | Hum: " + String(humidity, 2) + "%RH";
  msgS3 += " | Smoke: " + String(smoke, 2) + "ppm";
  String msgC3 = "ESP32(Node:";
  msgC3 += mesh.getNodeId();
  msgC3 += ") has received smoke concentration data";
  mesh.sendSingle(ESP32S3_NODE, msgS3);
  mesh.sendSingle(ESP32C3_NODE, msgC3);
  taskSendMessage.setInterval(TASK_SECOND * 1);
}
// 回调函数,提取ESP32-C3发来的烟雾浓度数据
// 接收到ESP32-C3消息示例：ESP32C3 Node 2030530093 | Smoke concentration: 3.53ppm
void receivedCallback(uint32_t from, String &msg) {
  Serial.printf("Received from %u: %s\n", from, msg.c_str());
  int smokePos = msg.indexOf("Smoke concentration: ");
  if (smokePos != -1) {
    smoke = msg.substring(smokePos + 21, msg.indexOf("ppm", smokePos)).toFloat();
    Serial.printf("Extracted Smoke: %.2f ppm\n", smoke);
  }
}

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("New Connection: nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.println("Connections changed");
}

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Time adjusted: Offset = %d\n", offset);
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  mesh.setDebugMsgTypes(ERROR | STARTUP);
  mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  // 添加任务到调度器
  userScheduler.addTask(taskSendMessage);
  userScheduler.addTask(taskReadDHT);
  
  taskSendMessage.enable();
  taskReadDHT.enable();
}

void loop() {
  mesh.update();
}
